package cn.growthgate.fgo.web;

import java.awt.image.BufferedImage;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.shiro.authz.annotation.RequiresUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.google.code.kaptcha.impl.DefaultKaptcha;

import cn.growthgate.fgo.common.Constants;
import cn.growthgate.fgo.entity.Image;
import cn.growthgate.fgo.entity.LoginLog;
import cn.growthgate.fgo.entity.User;
import cn.growthgate.fgo.entity.UserRole;
import cn.growthgate.fgo.entity.enums.Role;
import cn.growthgate.fgo.exception.UsernamePasswordException;
import cn.growthgate.fgo.service.IImageService;
import cn.growthgate.fgo.service.ILoginLogService;
import cn.growthgate.fgo.service.IUserRoleService;
import cn.growthgate.fgo.service.IUserService;
import cn.growthgate.fgo.util.AuthenticationUtils;
import cn.growthgate.fgo.util.RequestUtils;
import cn.growthgate.fgo.util.SpringUtils;
import cn.growthgate.fgo.util.StringUtils;
import cn.growthgate.fgo.web.result.JsonResult;
import eu.bitwalker.useragentutils.UserAgent;

/**
 * 首页Controller
 * 
 * @author GrowthGate
 * @since 2019年1月22日
 *
 */
@Controller
public class IndexController {

	@Autowired
	private IUserService userService;

	@Autowired
	private IUserRoleService userRoleService;

	@Autowired
	private IImageService imageService;

	@Autowired
	private ILoginLogService loginLogService;

	@RequestMapping("")
	public String index(HttpSession session) {
		session.removeAttribute(Constants.SESSION_LOGIN_REQUEST_URL);
		return "index";
	}

	/** 用户名、密码最大错误次数 */
	private static final int USERNAME_PASSWORD_ERROR_COUNT = 2;

	@RequestMapping("/login")
	public String login(HttpServletRequest request, HttpSession session) {
		// 获取上一个页面（如果上一个页面为登录页面，改为获取首页）
		String referer = RequestUtils.getRefererUrl(request);
		referer = referer.contains("login") || referer.contains("register") ? "/" : referer;
		if (AuthenticationUtils.isAuthenticated()) {
			// 如果已登录，跳转回上一个页面
			return "redirect:" + referer;
		}
		if (session.getAttribute(Constants.SESSION_LOGIN_REQUEST_URL) == null) {
			// 在session中保存上一个页面
			request.setAttribute("usernamePasswordErrorCount", Constants.SESSION_LOGIN_REQUEST_URL);
		}
		request.setAttribute("usernamePasswordErrorCount", USERNAME_PASSWORD_ERROR_COUNT);
		return "login";
	}

	@ResponseBody
	@RequestMapping(value = "/captcha", produces = MediaType.IMAGE_PNG_VALUE)
	public BufferedImage captcha(HttpSession session) {
		DefaultKaptcha kaptcha = SpringUtils.getBean(DefaultKaptcha.class);
		// 验证码文本
		String kaptchaText = kaptcha.createText();
		session.setAttribute(Constants.SESSION_CAPTCHA, kaptchaText);
		// 验证码图片
		BufferedImage bufferedImage = kaptcha.createImage(kaptchaText);
		return bufferedImage;
	}

	@ResponseBody
	@RequestMapping(value = "/doLogin", method = RequestMethod.POST)
	public JsonResult doLogin(@Validated(User.Login.class) User user, BindingResult bindingResult, String captcha,
			@RequestParam(defaultValue = "false") Boolean rememberMe, HttpSession session, HttpServletRequest request) {
		if (bindingResult.hasErrors()) {
			return JsonResult.fail(bindingResult.getAllErrors().get(0).getDefaultMessage());
		}
		// 验证码校验
		Integer showCaptcha = (Integer) session.getAttribute(Constants.SESSION_REQUEST_CAPTCHA);
		showCaptcha = showCaptcha == null ? 0 : showCaptcha;
		if (showCaptcha >= USERNAME_PASSWORD_ERROR_COUNT) {
			if (StringUtils.isBlank(captcha)) {
				return JsonResult.fail("验证码不能为空");
			}
			String kaptchaText = (String) session.getAttribute(Constants.SESSION_CAPTCHA);
			if (kaptchaText == null) {
				return JsonResult.fail("请刷新验证码");
			}
			if (!kaptchaText.equals(captcha.toUpperCase())) {
				session.removeAttribute(Constants.SESSION_CAPTCHA);
				return JsonResult.fail("验证码不正确").set("refreshCaptcha", true);
			}
		}
		try {
			AuthenticationUtils.doLogin(user, rememberMe);
		} catch (UsernamePasswordException e) {
			if (showCaptcha <= USERNAME_PASSWORD_ERROR_COUNT) {
				// 错误次数加一
				session.setAttribute(Constants.SESSION_REQUEST_CAPTCHA, ++showCaptcha);
			}
			JsonResult result = JsonResult.fail(e.getLocalizedMessage());
			if (showCaptcha >= USERNAME_PASSWORD_ERROR_COUNT) {
				// 输入密码错误达到一定次数，要求输入验证码
				result.set("requestCaptcha", true);
			}
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return JsonResult.fail(e.getLocalizedMessage());
		}
		user = AuthenticationUtils.getLoginUser();
		String url = (String) session.getAttribute(Constants.SESSION_LOGIN_REQUEST_URL);
		if (StringUtils.isBlank(url)) {
			url = AuthenticationUtils.DEFAULT_SUCCESS_URL;
		}
		// 清除session
		session.removeAttribute(Constants.SESSION_CAPTCHA);
		session.removeAttribute(Constants.SESSION_REQUEST_CAPTCHA);
		session.removeAttribute(Constants.SESSION_LOGIN_REQUEST_URL);
		// 记录日志
		String userAgentStr = request.getHeader("User-Agent");
		UserAgent userAgent = UserAgent.parseUserAgentString(userAgentStr);
		LoginLog loginLog = new LoginLog();
		loginLog.setUserId(user.getId());
		loginLog.setHost(RequestUtils.getIp(request));
		loginLog.setOs(userAgent.getOperatingSystem().getName());
		loginLog.setUa(userAgent.getBrowser().getName());
		loginLog.setUaVersion(userAgent.getBrowserVersion().toString());
		loginLogService.insert(loginLog);
		user.setLastLoginTime(new Date());
		userService.updateById(user);
		return JsonResult.ok("登录成功").set("url", url);
	}

	@RequestMapping("/register")
	public String register(HttpServletRequest request) {
		// 获取上一个页面（如果上一个页面为登录注册页面，改为获取首页）
		String referer = RequestUtils.getRefererUrl(request);
		referer = referer.contains("login") || referer.contains("register") ? "/" : referer;
		if (AuthenticationUtils.isUser()) {
			// 如果已登录，跳转回上一个页面
			return "redirect:" + referer;
		}
		return "register";
	}

	@ResponseBody
	@RequestMapping(value = "/doRegister", method = RequestMethod.POST)
	public JsonResult doRegister(@Validated(User.Register.class) User user, BindingResult bindingResult,
			String repass) {
		if (bindingResult.hasErrors()) {
			return JsonResult.fail(bindingResult.getAllErrors().get(0).getDefaultMessage());
		}
		if (!user.getPassword().equals(repass)) {
			return JsonResult.fail("密码不匹配");
		}
		User existsUser = userService.getByUsername(user.getUsername());
		if (existsUser != null) {
			return JsonResult.fail("用户名已被使用");
		}
		existsUser = userService.getByName(user.getName());
		if (existsUser != null) {
			return JsonResult.fail("昵称已被使用");
		}
		if (!userService.create(user)) {
			return JsonResult.fail("注册失败！详询网站管理员");
		}
		// 默认普通用户权限
		UserRole userRole = new UserRole();
		userRole.setUserId(user.getId());
		userRole.setRole(Role.USER);
		userRoleService.insert(userRole);
		return JsonResult.ok("注册成功！现在为您跳转到登录页面");
	}

	@RequiresUser
	@RequestMapping("/doLogout")
	public String doLogout() {
		AuthenticationUtils.doLogout();
		return "redirect:/";
	}

	@RequiresUser
	@RequestMapping("/info")
	public ModelAndView info(HttpServletRequest request) {
		User entity = AuthenticationUtils.getLoginUser();

		return new ModelAndView("info").addObject("entity", entity);
	}

	@RequiresUser
	@ResponseBody
	@RequestMapping("/saveInfo")
	public JsonResult saveInfo(@Validated(User.Update.class) User user, BindingResult bindingResult) {
		if (bindingResult.hasErrors()) {
			return JsonResult.fail(bindingResult.getAllErrors().get(0).getDefaultMessage());
		}
		// 编辑用户
		User oUser = AuthenticationUtils.getLoginUser();
		if (!oUser.getName().equals(user.getName())) {
			User existsUser = userService.getByName(user.getName());
			if (existsUser != null) {
				return JsonResult.fail("昵称已被使用");
			}
		}
		// 更改图片
		if (oUser.getAvatar() != null && !oUser.getAvatar().equals(user.getAvatar())) {
			imageService.deleteByEntity(oUser.getClass().getSimpleName(), oUser.getId());
			oUser.setAvatar(user.getAvatar());
		}
		oUser.setName(user.getName());
		oUser.setSex(user.getSex());
		oUser.setClient(user.getClient());
		oUser.setPyCode(user.getPyCode());
		if (!userService.updateAllColumnById(oUser)) {
			return JsonResult.fail("编辑用户失败");
		}
		user = oUser;
		if (StringUtils.isNotBlank(user.getAvatar())) {
			Image image = imageService.getByUUID(user.getAvatar());
			image.setEntityId(user.getId());
			image.setEntityName(user.getClass().getSimpleName());
			imageService.updateById(image);
		}
		// 更新用户信息
		AuthenticationUtils.updateLoginSimpleUser();
		return JsonResult.ok();
	}

	@RequiresUser
	@RequestMapping("/modifyPassword")
	public String modifyPassword() {
		return "modifyPassword";
	}

	@RequiresUser
	@ResponseBody
	@RequestMapping("/doModifyPassword")
	public JsonResult doModifyPassword(String password, String repass) {
		if (StringUtils.isAnyBlank(password, repass)) {
			return JsonResult.fail("必填项不能为空");
		}
		if (password.length() < 6) {
			return JsonResult.fail("密码必须大于6位");
		}
		if (!password.equals(repass)) {
			return JsonResult.fail("密码不匹配");
		}
		User user = AuthenticationUtils.getLoginUser();
		userService.setPassword(user, password);
		if (!userService.updateById(user)) {
			return JsonResult.fail("修改密码失败");
		}
		return JsonResult.ok("修改密码成功");
	}

}
